/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-13
 * V4.0
 */
package com.jphenix.webserver.instancea;

import com.jphenix.standard.docs.ClassInfo;

import javax.servlet.Servlet;
import javax.servlet.http.HttpServlet;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 * 路径树处理类
 * 
 * 2019-09-17 整理了代码格式
 * 
 * @author 刘虻
 * 2006-9-15上午12:08:44
 */
@ClassInfo({"2019-09-17 10:38","路径树处理类"})
public class PathTreeDictionary {
	
	private Node rootNode = null; //树根

	/**
	 * 构造函数
	 * 2007-9-30下午04:50:32
	 */
	public PathTreeDictionary() {
		rootNode = new Node();
	}

	
	/**
	 * 将Servlet放入节点
	 * @author 刘虻
	 * 2008-6-29下午07:05:44
	 * @param key 主键
	 * @param value Servlet
	 */
	protected void putServlet(String key,Servlet value) {
		//获取子节点
		Node node = (Node)rootNode.get(key);
		if (node==null) {
			node = new Node();
			rootNode.put(key,node);
		}
		node.object = value;
	}
	
	
	
	/**
	 * 放入节点
	 * @author 刘虻
	 * 2007-9-30下午04:51:18
	 * @param path 路径
	 * @param value 值
	 */
	public synchronized void put(String path, Servlet value) {
		if ("/".equals(path)) {
			rootNode.object = value;
		}
		//分段
		String[] paths = path.split("/");
		for(int i=0;i<paths.length;i++) {
			if (paths[i].length()<1) {
				continue;
			}
			if (i==paths.length-1) {
				if (paths[i].length()<1) {
					putServlet("*",value);
					return;
				}
				//扩展名分隔符
				int point = paths[i].indexOf(".");
				if (point>-1) {
					paths[i] = paths[i].substring(point+1);
				}
				putServlet(paths[i],value);
				return;
			}else {
				putServlet(paths[i],value);
			}
		}
	}
	

	/**
	 * 移除节点
	 * @author 刘虻
	 * 2007-9-30下午04:52:56
	 * @param value 节点值
	 * @return
	 */
	public synchronized HttpServlet remove(Object value) {
		return remove(rootNode, value);
	}

	/**
	 * 从容器中移除Servlet
	 * @author 刘虻
	 * 2008-6-29下午08:07:36
	 * @param path 路径
	 * @return Servlet
	 */
	public synchronized HttpServlet remove(String path) {
		HttpServlet result = get(path);
		if (result!=null) {
			return remove(result);
		}
		return result;
	}

	/**
	 * 从容器中移除指定Servlet
	 * @author 刘虻
	 * 2008-6-29下午08:08:35
	 * @param node Servlet 根
	 * @param value 指定Servlet
	 * @return 移除的Servlet
	 */
	public HttpServlet remove(Node node, Object value) {
		Enumeration<String> e = node.keys();
		while (e.hasMoreElements()) {
			String path = e.nextElement();
			Node childNode = (Node) node.get(path);
			if (childNode.object == value) // it's safe because the same instance can't be shared for several paths in this design
            {
                return (HttpServlet)value;
            }
			return remove(childNode, value);
		}
		return null;
	}
	
	
	/**
	 * 通过URL获取指定的Servlet
	 * @author 刘虻
	 * 2008-6-29下午06:27:46
	 * @param path URL
	 * @return Servlet 
	 */
	public HttpServlet get(String path) {
		String extName = "";
		int point = path.indexOf("."); //扩展名分割点
		if (point>-1) {
			extName = path.substring(point+1);
			path = path.substring(0,point);
		}
		return get(path,extName);
	}


	/**
	 * 通过URL获取指定的Servlet
	 * @author 刘虻
	 * 2008-6-29下午06:27:46
	 * @param path URI
	 * @param extName 扩展名
	 * @return Servlet 
	 */
	public HttpServlet get(String path,String extName) {
		//构建返回值
		HttpServlet result = null;
		if (path == null) {
			return result;
		}
		//获取根节点
		Node curNode = (Node)rootNode.get(extName);
		if (curNode==null || curNode.object==null) {
			curNode = rootNode;
		}
		//设置默认返回Servlet
		result = (HttpServlet)curNode.object;
		
		int p0 = 0; //目录分割位置
		//构造路径数组
		char[] ps = path.toCharArray();
		
		boolean divState = true;

		for (int i=0; i<ps.length; i++) {
			if (ps[i]=='/' || ps[i]=='\\') {
				if (divState) {
					continue;
				}
				//获取路径对应的节点
				Node node = (Node) curNode.get(new String(ps,p0,i-p0));
				if (node!=null && node.object!=null) {
					curNode = node;
					result = (HttpServlet)curNode.object;
				}
				divState = true;
			} else {
				if (divState) {
					p0 = i;
					divState = false;
				}
			}
		}
		//通过扩展名获取对应的Servlet
		Node node = (Node)curNode.get(extName);
		if (node!=null && node.object!=null) {
			curNode = node;
			result = (HttpServlet)curNode.object;
		}
		return result;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-8下午06:46:52
	 * @return 母鸡
	 */
	public Enumeration<String> keys() {
		Vector<String> result = new Vector<String>();
		addSiblingNames(rootNode, result, "");
		return result.elements();
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-8下午06:46:59
	 * @param node 母鸡
	 * @param result 母鸡
	 * @param path 母鸡
	 */
	public void addSiblingNames(Node node, Vector<String> result, String path) {
		Enumeration<String> e = node.keys();
		while (e.hasMoreElements()) {
			String pc = e.nextElement();
			Node childNode = (Node) node.get(pc);
			pc = path + '/' + pc;
			if (childNode.object != null) {
                result.addElement(pc);
            }
			addSiblingNames(childNode, result, pc);
		}
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-8下午06:47:08
	 * @return 母鸡
	 */
	public Enumeration<Servlet> elements() {
		Vector<Servlet> result = new Vector<Servlet>();
		addSiblingObjects(rootNode, result);
		return result.elements();
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-8下午06:47:12
	 * @param node 母鸡
	 * @param result 母鸡
	 */
	public void addSiblingObjects(Node node, Vector<Servlet> result) {
		Enumeration<String> e = node.keys();
		while (e.hasMoreElements()) {
			Node childNode = (Node) node.get(e.nextElement());
			if (childNode.object != null) {
                result.addElement(childNode.object);
            }
			addSiblingObjects(childNode, result);
		}
	}

	
	/**
	 * 节点类
	 * @author 刘虻
	 * 2008-7-8下午06:47:54
	 */
	protected class Node extends Hashtable<String,Object> {
		/**
		 * 版本标识
		 */
		private static final long serialVersionUID = 8662335400180397442L;
		protected Servlet object;
	}
}